<p>Having a permissive Cross-Origin Resource Sharing policy is security-sensitive. It has led in the past to the following vulnerabilities:</p>
<ul>
  <li> <a href="https://www.cve.org/CVERecord?id=CVE-2018-0269">CVE-2018-0269</a> </li>
  <li> <a href="https://www.cve.org/CVERecord?id=CVE-2017-14460">CVE-2017-14460</a> </li>
</ul>
<p><a href="https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy">Same origin policy</a> in browsers prevents, by default and for
security-reasons, a javascript frontend to perform a cross-origin HTTP request to a resource that has a different origin (domain, protocol, or port)
from its own. The requested target can append additional HTTP headers in response, called <a
href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS">CORS</a>, that act like directives for the browser and change the access control policy
/ relax the same origin policy.</p>
<h2>Ask Yourself Whether</h2>
<ul>
  <li> You don’t trust the origin specified, example: <code>Access-Control-Allow-Origin: untrustedwebsite.com</code>. </li>
  <li> Access control policy is entirely disabled: <code>Access-Control-Allow-Origin: *</code> </li>
  <li> Your access control policy is dynamically defined by a user-controlled input like <a
  href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin"><code>origin</code></a> header. </li>
</ul>
<p>There is a risk if you answered yes to any of those questions.</p>
<h2>Recommended Secure Coding Practices</h2>
<ul>
  <li> The <code>Access-Control-Allow-Origin</code> header should be set only for a trusted origin and for specific resources. </li>
  <li> Allow only selected, trusted domains in the <code>Access-Control-Allow-Origin</code> header. Prefer whitelisting domains over blacklisting or
  allowing any domain (do not use * wildcard nor blindly return the <code>Origin</code> header content without any checks). </li>
</ul>
<h2>Sensitive Code Example</h2>
<p>ASP.NET Core MVC:</p>
<pre>
[HttpGet]
public string Get()
{
    Response.Headers.Add("Access-Control-Allow-Origin", "*"); // Sensitive
    Response.Headers.Add(HeaderNames.AccessControlAllowOrigin, "*"); // Sensitive
}
</pre>
<pre>
public void ConfigureServices(IServiceCollection services)
{
    services.AddCors(options =&gt;
    {
        options.AddDefaultPolicy(builder =&gt;
        {
            builder.WithOrigins("*"); // Sensitive
        });

        options.AddPolicy(name: "EnableAllPolicy", builder =&gt;
        {
            builder.WithOrigins("*"); // Sensitive
        });

        options.AddPolicy(name: "OtherPolicy", builder =&gt;
        {
            builder.AllowAnyOrigin(); // Sensitive
        });
    });

    services.AddControllers();
}
</pre>
<p>ASP.NET MVC:</p>
<pre>
public class HomeController : ApiController
{
    public HttpResponseMessage Get()
    {
        var response = HttpContext.Current.Response;

        response.Headers.Add("Access-Control-Allow-Origin", "*"); // Sensitive
        response.Headers.Add(HeaderNames.AccessControlAllowOrigin, "*"); // Sensitive
        response.AppendHeader(HeaderNames.AccessControlAllowOrigin, "*"); // Sensitive
    }
}
</pre>
<pre>
[EnableCors(origins: "*", headers: "*", methods: "GET")] // Sensitive
public HttpResponseMessage Get() =&gt; new HttpResponseMessage()
{
    Content = new StringContent("content")
};
</pre>
<p>User-controlled origin:</p>
<pre>
String origin = Request.Headers["Origin"];
Response.Headers.Add("Access-Control-Allow-Origin", origin); // Sensitive
</pre>
<h2>Compliant Solution</h2>
<p>ASP.NET Core MVC:</p>
<pre>
[HttpGet]
public string Get()
{
    Response.Headers.Add("Access-Control-Allow-Origin", "https://trustedwebsite.com"); // Safe
    Response.Headers.Add(HeaderNames.AccessControlAllowOrigin, "https://trustedwebsite.com"); // Safe
}
</pre>
<pre>
public void ConfigureServices(IServiceCollection services)
{
    services.AddCors(options =&gt;
    {
        options.AddDefaultPolicy(builder =&gt;
        {
            builder.WithOrigins("https://trustedwebsite.com", "https://anothertrustedwebsite.com"); // Safe
        });

        options.AddPolicy(name: "EnableAllPolicy", builder =&gt;
        {
            builder.WithOrigins("https://trustedwebsite.com"); // Safe
        });
    });

    services.AddControllers();
}
</pre>
<p>ASP.Net MVC:</p>
<pre>
public class HomeController : ApiController
{
    public HttpResponseMessage Get()
    {
        var response = HttpContext.Current.Response;

        response.Headers.Add("Access-Control-Allow-Origin", "https://trustedwebsite.com");
        response.Headers.Add(HeaderNames.AccessControlAllowOrigin, "https://trustedwebsite.com");
        response.AppendHeader(HeaderNames.AccessControlAllowOrigin, "https://trustedwebsite.com");
    }
}
</pre>
<pre>
[EnableCors(origins: "https://trustedwebsite.com", headers: "*", methods: "GET")]
public HttpResponseMessage Get() =&gt; new HttpResponseMessage()
{
    Content = new StringContent("content")
};
</pre>
<p>User-controlled origin validated with an allow-list:</p>
<pre>
String origin = Request.Headers["Origin"];

if (trustedOrigins.Contains(origin))
{
    Response.Headers.Add("Access-Control-Allow-Origin", origin);
}
</pre>
<h2>See</h2>
<ul>
  <li> OWASP - <a href="https://owasp.org/Top10/A05_2021-Security_Misconfiguration/">Top 10 2021 Category A5 - Security Misconfiguration</a> </li>
  <li> OWASP - <a href="https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures/">Top 10 2021 Category A7 - Identification and
  Authentication Failures</a> </li>
  <li> <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS">developer.mozilla.org</a> - CORS </li>
  <li> <a href="https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy">developer.mozilla.org</a> - Same origin policy </li>
  <li> OWASP - <a href="https://owasp.org/www-project-top-ten/2017/A6_2017-Security_Misconfiguration">Top 10 2017 Category A6 - Security
  Misconfiguration</a> </li>
  <li> <a href="https://cheatsheetseries.owasp.org/cheatsheets/HTML5_Security_Cheat_Sheet.html#cross-origin-resource-sharing">OWASP HTML5 Security
  Cheat Sheet</a> - Cross Origin Resource Sharing </li>
  <li> CWE - <a href="https://cwe.mitre.org/data/definitions/346">CWE-346 - Origin Validation Error</a> </li>
  <li> CWE - <a href="https://cwe.mitre.org/data/definitions/942">CWE-942 - Overly Permissive Cross-domain Whitelist</a> </li>
</ul>

